package com.sotb.sender;

import android.app.PendingIntent;
import android.app.PendingIntent.CanceledException;
import android.content.Context;
import android.content.Intent;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;

/**@author zsr 
 * 该类用于获取地理位置信息<br>
 * <p>startListening()	开始监听<br>
 * stopListening()	停止监听
 */
public class LocationInfo {
	private static final int TWO_MINUTES = 1000 * 60 * 2;	//用于判断location的新旧程度
	private long timeToListen;	//监听时间，时间越长定位越精确
	private LocationManager locationManager = null;
	private Context context = null;
	private MyLocationListener myLocationListener;
	private boolean flag;	//循环监听标记
	double[] latlang = {0,0};	//存储经纬度
	boolean hasNew = false;	//标记是否有新的location
	
	/**构造函数
	 * @param context 用于获取系统服务，从而得到位置监听功能
	 */
	LocationInfo(Context context){
		this.context = context;
		myLocationListener = new MyLocationListener();
		locationManager = (LocationManager)context.getSystemService(Context.LOCATION_SERVICE);
		locationManager.requestLocationUpdates(getBetterProvider(), 0, 0, myLocationListener);
	}
	
	/**获取地理位置(费时操作，阻塞线程)；可调用stop()主动结束监听
	 * @param handler 处理消息
	 * @param time 自定义监听时间
	 * */
	public void startListening(Handler handler, long time){
		timeToListen = time;
		flag = true;
		if (!locationManager.isProviderEnabled(android.location.LocationManager.GPS_PROVIDER))enableGPS();
		try {
			Thread.sleep(10000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		//当调用stop()或者超过设置的时间时停止监听
		while(flag && timeToListen > 0){
			timeToListen += System.currentTimeMillis();
			//当有新的较好位置时发送到handler
			if(hasNew){
				Message msg = handler.obtainMessage();
				msg.obj = latlang;
				msg.sendToTarget();
				System.out.println("msg sent");
				hasNew = false;
			}
			try {
				Thread.sleep(20000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			timeToListen -= System.currentTimeMillis();
		}
		stopListening();
	}
	
	/**停止监听*/
	public void stopListening(){
		this.flag = false;
		locationManager.removeUpdates(myLocationListener);
		disableGPS();
	}
	
	/**开启GPS*/
	private void enableGPS(){
		if(!locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)){
			changeGPSState();
	        System.out.println("GPS has been opened");
		}
	}
	
	/**关闭GPS*/
	private void disableGPS(){
		if(locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)){
			changeGPSState();
	        System.out.println("GPS has been closed");
		}
	}
	
	/**改变gps的开关状态*/
	private void changeGPSState(){
		Intent gpsIntent = new Intent();
        gpsIntent.setClassName("com.android.settings",
                        "com.android.settings.widget.SettingsAppWidgetProvider");
        gpsIntent.addCategory("android.intent.category.ALTERNATIVE");
        gpsIntent.setData(Uri.parse("custom:3"));
        try {
                PendingIntent.getBroadcast(context, 0, gpsIntent, 0).send();
        }
        catch (CanceledException e) {
                e.printStackTrace();
        }
	}
	
	/** 获取较好的Location provider
	 * @return String 代表provider类型，如"gps"
	 */
	private String getBetterProvider(){
		Criteria criteria = new Criteria();
		criteria.setAccuracy(Criteria.ACCURACY_FINE);
		criteria.setAltitudeRequired(false);
		criteria.setCostAllowed(true);
		criteria.setSpeedAccuracy(Criteria.POWER_LOW);
		criteria.setSpeedRequired(false);
		if(locationManager.getBestProvider(criteria, true)==null)return "gps";
		else return locationManager.getBestProvider(criteria, true);
	}
	
	/**location监听器*/
	private class MyLocationListener implements LocationListener{
		private Location currentBestLocation = null;
		public void onLocationChanged(Location location) {
			if(isBetterLocation(location, currentBestLocation)){
				currentBestLocation = location;
				latlang[0] = location.getLongitude();
				latlang[1] = location.getLatitude();
				hasNew = true;
			}
			if(currentBestLocation != null)System.out.println("new location");
		}

		public void onProviderDisabled(String provider) {
			
		}

		public void onProviderEnabled(String provider) {
			
		}

		public void onStatusChanged(String provider, int status, Bundle extras) {
			
		}
		
		/** 判断新获取的location是否比旧的location好
		  * @param location	新获取的location
		  * @param currentBestLocation	当前location
		  */
		protected boolean isBetterLocation(Location location, Location currentBestLocation){
			if (currentBestLocation == null) {
				return true;
		    }
		
		    //比较location的新旧
		    long timeDelta = location.getTime() - currentBestLocation.getTime();
		    boolean isSignificantlyNewer = timeDelta > TWO_MINUTES;
		    boolean isSignificantlyOlder = timeDelta < -TWO_MINUTES;
		    boolean isNewer = timeDelta > 0;
		
		    //location时间间隔超过两分钟则强制更新
		    if (isSignificantlyNewer) {
		        return true;
		    } else if (isSignificantlyOlder) {
		        return false;
		    }
		
		    //比较精确度
		    int accuracyDelta = (int) (location.getAccuracy() - currentBestLocation.getAccuracy());
		    boolean isLessAccurate = accuracyDelta > 0;
		    boolean isMoreAccurate = accuracyDelta < 0;
		    boolean isSignificantlyLessAccurate = accuracyDelta > 200;
		
		    boolean isFromSameProvider = isSameProvider(location.getProvider(),
		            currentBestLocation.getProvider());
		
		    //结合时间和精度比较
		    if (isMoreAccurate) {
		        return true;
		    } else if (isNewer && !isLessAccurate) {
		        return true;
		    } else if (isNewer && !isSignificantlyLessAccurate && isFromSameProvider) {
		        return true;
		    }
		    return false;
		}
		
		/**检测两个provider是否相同*/
		private boolean isSameProvider(String provider1, String provider2) {
		    if (provider1 == null) {
		      return provider2 == null;
		    }
		    return provider1.equals(provider2);
		}
    }
}
